package com.helloscala.web

import net.liftweb.http._
import net.liftweb.common.{Box, Full, Empty}
import net.liftweb.util.Helpers
import net.liftweb.sitemap.Loc.TestAccess

import com.helloscala.model._
import net.liftweb.http.provider.HTTPRequest
import com.helloscala.helper.HelloHelpers
import yangbajing.common.HostName
import com.helloscala.common.Tag

object W {

  object reqTag extends RequestVar[Box[Tag]](_findTag)

  object reqDocument extends RequestVar[Box[MDocument]](_findDocument)

  object reqUser extends RequestVar[Box[MUser]](_findUser)

  object reqMicroChat extends RequestVar[Box[MMicroChat]](_findMicroChat)

  object theAccount extends SessionVar[Box[Account]](Empty)

  def testSession = TestAccess(() =>
    theAccount.is match {
      case Full(account) =>
        Empty

      case _ =>
        val url = (S.uriAndQueryString.openOr(S.uri) match {
          case "/" => Empty
          case uri if uri.startsWith("/index") => Empty
          case uri => Full(uri)
        }).map(S.hostAndPath + _)
        val toUrl = W.href("/c/sign_in" + url.map(v => "?goto_page=" + Helpers.urlEncode(v)).getOrElse(""))
        Full(RedirectResponse(toUrl))
    })

  def testAdmin = TestAccess(() =>
    theAccount.is match {
      case Full(account) if account.user.isAdmin =>
        Empty

      case Full(account) =>
        S.error(s"账号：${account.id} 权限不足。")
        Full(RedirectResponse(href("/index")))

      case _ =>
        val url = (S.uriAndQueryString.openOr(S.uri) match {
          case "/" => Empty
          case uri if uri.startsWith("/index") => Empty
          case uri => Full(uri)
        }).map(S.hostAndPath + _)
        val toUrl = W.href("/c/sign_in" + url.map(v => "?goto_page=" + Helpers.urlEncode(v)).getOrElse(""))
        Full(RedirectResponse(toUrl))
    })

  def testSiteIdForDocument = TestAccess(() =>
    siteLevel2 match {
      case Full(hn) if reqDocument.is.exists(_.author != hn.siteId) =>
        Full(RedirectResponse(href("/404")))
      case _ =>
        Empty
    })

  def testSignUp = TestAccess(() => {
    if (HelloHelpers.config.allowed_register)
      Empty
    else
      Full(RedirectResponse(href404("页面不存在", "您访问的页面不存！")))
  })

  def signOut = TestAccess(() => {
    W.theAccount.remove()
    Full(RedirectResponse(href("/index")))
  })

  def saveSessionAndCookie(user: MUser, remember: Boolean = true, data: AnyRef = null) {
    assert(user ne null)

    val account = Account(user.id, user, Option(data))
    W.theAccount(Full(account))
  }

  def templateSignUp =
    Templates(List("c", "_sign_up")).openOrThrowException("/c/_sign_up not found!")

  def templateSignIn =
    Templates(List("c", "_sign_in")).openOrThrowException("/c/_sign_in not found!")

  def siteLevel2: Box[HostName] = {
    val result = for {
      req <- S.request
      request <- Box.!!(req.request)
    } yield siteLevel2(request)

    result openOr Empty
  }

  def siteLevel2(req: HTTPRequest): Box[HostName] =
    if (HelloHelpers.config.two_domain_support)
      req.serverName.split('.') match {
        case Array(ValidSiteId(id), name, domain) => _makeHostName(id, name, domain, req)
        case Array(name, domain) => _makeHostName("www", name, domain, req)
        case _ => Empty
      }
    else
      Empty

  @inline
  private def _makeHostName(siteId: String, name: String, domain: String, req: HTTPRequest): Full[HostName] = {
    val schema = req.scheme match {
      case "http" if req.header("X-SSL").isDefined => "https"
      case sch => sch
    }
    Full(HostName(schema, siteId, name, domain, req.serverPort, req.contextPath))
  }

  def siteId: Box[String] =
    siteLevel2.map(_.siteId)

  def equalSiteId(id: String): Boolean =
    siteId.map(v => v == "www" || v == id).openOr(true)

  def hrefParams(path: String, params: (String, String)*): String =
    href(path + params.map(v => v._1 + "=" + Helpers.urlEncode(v._2)).mkString("?", "&", ""))

  def hrefBase64Params(path: String, params: (String, String)*): String =
    href(path + params.map(v => v._1 + "=" + Helpers.base64EncodeURLSafe(v._2.getBytes("UTF-8"))).mkString("?", "&", ""))

  def href404(title: String, content: String): String =
    hrefBase64Params("/404", "title" -> title, "content" -> content)

  def href500(title: String, content: String): String =
    hrefBase64Params("/500", "title" -> title, "content" -> content)

  def hrefTag(tag: String): String =
    href(s"/tag/${Helpers.urlEncode(tag)}")

  def hrefDocumentEdit(siteId: String, id: String): String =
    siteLevel2 match {
      case Full(hn) => hn.url(siteId, s"/document/${Helpers.urlEncode(id)}/edit")
      case _ => s"/$siteId/document/${Helpers.urlEncode(id)}/edit"
    }

  def hrefDocumentNew(siteId: String): String =
    siteLevel2 match {
      case Full(hn) => hn.url(siteId, "/document/new")
      case _ => s"/$siteId/document/new"
    }

  def hrefDocument(siteId: String, id: String): String =
    siteLevel2 match {
      case Full(hn) => hn.url(siteId, s"/document/${Helpers.urlEncode(id)}")
      case _ => s"/$siteId/document/${Helpers.urlEncode(id)}"
    }

  def hrefUserTag(siteId: String, tagId: String): String =
    siteLevel2 match {
      case Full(hn) => hn.url(siteId, s"/tag/${Helpers.urlEncode(tagId)}")
      case _ => s"/$siteId/tag/${Helpers.urlEncode(tagId)}"
    }

  def hrefUserTag(siteId: String): String =
    siteLevel2 match {
      case Full(hn) => hn.url(siteId, "/tag")
      case _ => s"/$siteId/tag"
    }

  def hrefUser(siteId: String): String =
    siteLevel2 match {
      case Full(hn) => hn.url(siteId)
      case _ => "/" + siteId
    }

  def hrefUserDetail(siteId: String): String =
    siteLevel2 match {
      case Full(hn) => hn.url(siteId, "/detail")
      case _ => s"/$siteId/detail"
    }

  def hrefMicroChat(siteId: String, id: String): String =
    siteLevel2 match {
      case Full(hn) => hn.url(siteId, s"/micro_chat/${Helpers.urlEncode(id)}")
      case _ => s"/$siteId/micro_chat/${Helpers.urlEncode(id)}"
    }

  def hrefSearch(params: (String, String)*): String =
    W.href(
      "/p/search/index" +
        params.map(v => v._1 + "=" + Helpers.urlEncode(v._2)).mkString("?", "&", ""))

  def hrefGotoPage(path: String): String = {
    val url = S.param("goto_page") or (S.uriAndQueryString.openOr(S.uri) match {
      case "/" => Empty
      case uri if uri.startsWith("/index") => Empty
      case uri => Full(uri)
    }).map(v => Helpers.urlEncode(S.hostAndPath + v)) // TODO 判断http或https ！！！
    val v = url.map("?goto_page=" + _).getOrElse("")
    href(path + v)
  }

  def href(siteId: String, path: String): String =
    siteLevel2 match {
      case Full(hn) => hn.url(siteId, path)
      case _ => s"/${siteId + path}"
    }

  def href(path: String): String =
    siteLevel2 map (_.mainSite + path) openOr path

  private[this] def _findTag: Box[Tag] =
    H.param("tag_id").flatMap(MTag.findById)

  private[this] def _findDocument: Box[MDocument] =
    H.param("document_id").flatMap(MDocument.findOneById)

  private[this] def _findUser: Box[MUser] =
    H.param("user_id").flatMap(MUser.findById)

  private[this] def _findMicroChat: Box[MMicroChat] =
    for (
      userId <- H.param("user_id") ?~ "账号不存在";
      microChatId <- H.param("micro_chat_id");
      microChat <- MMicroChat.findById(microChatId)
    ) yield microChat

}
